#ifndef NAFIGATOR_H_
#define NAFIGATOR_H_


#include <pthread.h>
#include <img/img.h>
#include <screen/screen.h>
#include "utils.h"


#define ALPHA_SOLID             (0xff000000)
#define ALPHA_TRANSPARENT       (0x00000000)

#define CLR_DEFAULT_BGRND       (0x000000)      // default window background color (RGB)
#define CLR_TILE_FAILED         (0xffb5da)      // color to fill the tile buffer in case failed to load the image file

#define TILE_ZOOM               (8)             // The tile size is a power of 2. The value of 8 gives...
#define TILE_SIZE               (1 << TILE_ZOOM)// ...256 x 256 pixels tiles

#define MIN_ZOOM                (5)             // min supported map zoom level
#define MAX_ZOOM                (14)            // max supported map zoom level

#define FONT_HEIGHT             (28)            // font bitmap height (pixels)
#define FONT_WIDTH              (1440)          // font bitmap width (pixels)
#define FONT_NUM_CHARS          (96)            // number of characters in the font (after space ASCII 0x20)
#define FONT_BITMAP_PATH        "app/native/assets/unlearned.fon.png" // font characters bitmap
#define FONT_CHAR_OFFS_PATH     "app/native/assets/unlearned.fon.txt" // offset (pixels) of each character in bitmap by X axis

#define STAT_WINDOW_HEIGHT      (FONT_HEIGHT+4) // status bar window height (pixels)

#define WIN_ZOOM_WIDTH          (128)           // zoom button width (pixels)
#define WIN_ZOOM_HEIGHT         WIN_ZOOM_WIDTH  // zoom button height (pixels)
#define WIN_ZOOM_IN_IMG_PATH    "app/native/assets/zoom_in.png"  // zoom in button image path
#define WIN_ZOOM_OUT_IMG_PATH   "app/native/assets/zoom_out.png" // zoom out button image path

#define WIN_VEHICLE_WIDTH       (32)            // vehicle icon width (pixels)
#define WIN_VEHICLE_HEIGHT      WIN_VEHICLE_WIDTH  // vehicle icon height (pixels)
#define WIN_VEHICLE_IMG_PATH    "app/native/assets/vehicle.png"  // vehicle icon image path

#define GEO_IS_VALID_UTC        (1 << 0)        // UTC is valid
#define GEO_IS_VALID_SPEED      (1 << 1)        // Speed is valid
#define GEO_IS_VALID_ALTITUDE   (1 << 2)        // Altitude is valid
#define GEO_IS_VALID_ALT_ACCUR  (1 << 3)        // Altitude accuracy is valid
#define GEO_IS_VALID_HEADING    (1 << 4)        // Heading is valid
#define GEO_IS_VALID_NUM_SAT    (1 << 5)        // Number of satellites used is valid

#define LOG_HEADER_SIGNATURE    "NAFIGA"
#define LOG_HEADER_VERSION      1

#define ZORDER_WIN_MAIN         (0)
#define ZORDER_WIN_STAT         (1)
#define ZORDER_WIN_VEHICLE      (2)
#define ZORDER_WIN_ZOOM         (3)


/**
 * @typedef struct log_record_t
 * A data type to store the record of the geolocation trace
 */
typedef struct {
    uint32_t utc;               // seconds since the epoch (1970-01-01 00:00:00)
    sint32_t latitude;          // degrees * 10^7
    sint32_t longitude;         // degrees * 10^7
    sint32_t speed;             // m/s * 10^3
    sint16_t altitude;          // m
    uint16_t heading;           // degrees * 10^2
    uint16_t num_sat;           // number of satellites used
    sint16_t position_accuracy; // m
    sint16_t altitude_accuracy; // m
    uint16_t flags;             // bitwise OR of GEO_IS_VALID_* flags
} log_record_t;

/**
 * @typedef struct log_header_t
 * A data type to store the header of the geolocation trace
 */
typedef struct {
    uint8_t signature[6];       // log file signature
    uint16_t version;           // log file version
    uint16_t header_size;       // log file header size
    uint16_t record_size;       // log file record size
} log_header_t;

/**
 * @typedef struct int_coord_t
 * A data type to store integer coordinates
 */
typedef struct {
    int x;
    int y;
} int_coord_t;

/**
 * @typedef struct gps_data_t
 * A data type to store data provided by geolocation
 */
typedef struct {
    int_coord_t position;       // Position (pixels) on the global map at the max resolution, i.e. MAX_ZOOM + TILE_ZOOM
    int speed;                  // Speed (km/h)
    int altitude;               // Altitude (m above mean sea level)
    int heading;                // Heading (degrees)
    int num_sat;                // Number of satellites used
} geo_data_t;

/**
 * @typedef struct renderer_t
 * A data type to control screen renderer thread
 */
typedef struct {
    pthread_t thread;           // thread handle
    pthread_cond_t cond;
    pthread_mutex_t mutex;

    // Thread state flags
    int is_thread_exit:1;       // set true to have thread to exit
    int is_cond_init:1;         // true if cond has been initialized
    int is_mutex_init:1;        // true if mutex has been initialized
} renderer_t;

/**
 * @typedef struct buffer_t
 * A data type that contains the description of screen buffer
 */
typedef struct {
    screen_buffer_t bufh;       // buffer handle
    int w;                      // buffer width (in pixels)
    int h;                      // buffer height (in pixels)
    int stride;                 // buffer stride
    uint8_t *data;              // pointer to the actual graphics data
} buffer_t;

/**
 * @typedef struct pixmap_t
 * A data type that contains the description of pixmap
 */
typedef struct {
    screen_pixmap_t pxmh;       // pixmap handle
    buffer_t buf;               // pixmap buffer
} pixmap_t;

/**
 * @typedef struct win_main_t
 * A data type that contains the description of the main application window
 */
typedef struct {
    screen_window_t wndh;       // window handle
    int w;                      // window width (in pixels)
    int h;                      // window height (in pixels)
    buffer_t buf[2];            // window buffers
    int shadow_idx;             // the index of buf[] that is not currently being displayed (0 or 1)

    int cur_zoom;               // current zoom level
    int last_zoom;              // previous zoom level

    int_coord_t cur_pos;        // window current position. The window should be rendered so that it's centre is at the cur_pos
                                // Coordinates are measured in pixels on the global map at the current resolution, i.e. zoom + TILE_ZOOM
    int_coord_t last_pos;       // previous position of the window. Same measurement units as for cur_pos
    int_coord_t buf_pos;        // top left corner of the window buffer. Same measurement units as for cur_pos. Aligned to TILE_SIZE
} win_main_t;

/**
 * @typedef struct status_bar_param_t
 * A data type that contains the parameters displayed in the status bar
 */
typedef struct {
    int speed;                  // Speed (km/h)
    int altitude;               // Altitude (m above mean sea level)
    int heading;                // Heading (degrees)
    int num_sat;                // Number of satellites used
    int zoom;                   // Map zoom level
} status_bar_param_t;

/**
 * @typedef struct win_stat_t
 * A data type that contains the description of the status bar window
 */
typedef struct {
    screen_window_t wndh;       // window handle
    buffer_t buf;               // window buffer
    pixmap_t font;              // font characters
    int chr_off[FONT_NUM_CHARS+1];  // table of character offsets in the font

    // Parameters to display in the status bar
    status_bar_param_t cur;     // most recent parameters
    status_bar_param_t last;    // previous parameters
} win_stat_t;

/**
 * @typedef struct win_zoom_t
 * A data type that contains the description of the zoom button window
 */
typedef struct {
    screen_window_t wndh;       // window handle
    buffer_t buf;               // window buffer
} win_zoom_t;

/**
 * @typedef struct win_vehicle_t
 * A data type that contains the description of the vehicle icon, representing the current location
 */
typedef struct {
    screen_window_t wndh;       // window handle
    int w;                      // window width (in pixels)
    int h;                      // window height (in pixels)
    buffer_t buf;               // window buffer
} win_vehicle_t;

/**
 * @typedef struct app_state_t
 * A data type that represents the state of the application (data collected from different sensors)
 */
typedef struct {
    geo_data_t geo_data;        // data from geolocation provider
    int zoom;                   // zoom level

    int is_active:1;            // flag indicating if the app is active (foreground) or inactive (background)
    int is_geo_valid:1;         // flag indicating if the geo_data field contains valid data
} app_state_t;

/**
 * @typedef struct app_control_t
 * A data type that contains the structure for keeping application state
 */
typedef struct {
    screen_context_t ctxh;      // global screen context (for all windows)
    win_main_t win_main;        // main application window
    win_stat_t win_stat;        // status bar window
    win_zoom_t win_zoom_in;     // zoom in button window
    win_zoom_t win_zoom_out;    // zoom out button window
    win_vehicle_t win_vehicle;  // vehicle icon
    img_lib_t  imglib;          // image library handle
    renderer_t rend;            // screen renderer thread

    app_state_t state;          // Current application state. Protect access with rend.mutex

    FILE *log;                  // Geolocation log file
    dialog_instance_t dialog;   // Alert dialog to display important notes

    // Application state flags
    int is_app_exit:1;          // set true to have application exit

    // BPS flags
    int is_bps_init:1;          // true if BPS has been initialized
    int is_navigator_init:1;    // true if subscribed for navigator events
    int is_screen_init:1;       // true if subscribed for screen events
    int is_geolocation_init:1;  // true if subscribed for geolocation events
} app_control_t;

#endif /* NAFIGATOR_H_ */

